

if _G.RequireLuas ~= nil then           --导入本脚本所需的所有外部脚本
	for _,v in ipairs(_G.RequireLuas) do
		require(v);
	end
end
if _G.ScaleTime ~= nil then
	scaleTime = _G.ScaleTime;			--脚本相邻两次被调用的时间间隔
end
require("Util");
-- require("MonMap0");
require("RoleSkill");

local shcedule = 1;			--当前副本的进度
local mon_Threads = {};		--存储怪物线程集合
local role_Threads = {};	--存储角色线程集合

local skill_Box = {};
local skill_Round = {};
local skill_Full = {};

function Start()
	-- body
end

function Update()
	result = {};
	local roles = {
					-- {id = 100, x = 1.5, y = 1, HP = 100, AD = 10, AP = 12, AR = 10, MR = 10 },
					-- {id = 200, x = -39.4, y = 0.54, HP = 100, AD = 10, AP = 12, AR = 5, MR = 8}
				};

	local OutAICode = {EnterFight = 1, Position = 2, Idle = 3, CurrentHP = 4, Target = 5, Die = 6, Born = 7, GameOver = -1, CurrentOver = 8};		--服务器TO客户端
	local InAICode = {Init = 0, Enter = 1, Exit = 2, Attack = 3, CastSkill = 4, Ready = 5, Move = 6, ReadySchedule = 7, RoleCount = 8};						--客户端TO服务器
	local current_Mons = {};			--根据进度获取当前区域内怪物的信息
	local recheck_Target = 0;
	local currentReady = 0;			--当前已加载完成的玩家数量
	local waitflag = 1;					--开始时会进行一定时间的等待，直到所有成场景后才开玩家都加载完始进行计算
	local roleCount = 0;
	local readyFightCount = 0;      --当前进行战斗区域的玩家数量
	local readNext = 0;             --是否读入并生成当前区域的怪物


	local role_Functions = {};			--客户端发送过来的数据处理函数

	role_Functions["Fun"..InAICode.Init] = function(action)
		local mapID = action[2];
		require("MonMap"..mapID);
		coroutine.yield("include MonMap"..mapID);
	end

	role_Functions["Fun"..InAICode.Enter] = function(action)			--客户端加入
		--action = {op, ID, X, Y, AD, AP, AR, MR, 技能1， 技能2， 技能3};
		local newRole = {id = action[2], HP = action[3], AD = action[4], AP = action[5], AR = action[6], MR = action[7],
						kill1 = action[8], kill2 = action[9], kill3 = action[10], move = 0};
		-- newRole.x = BornPos.x;
		-- newRole.y = BornPos.y;
		-- table.insert(roles, newRole);
		roles["Role"..newRole.id] = newRole;
		-- table.insert(result, {OutAICode.Born, newRole.typeid, newRole.id, newRole.x, newRole.y});     --回发数据：出生
	end

	role_Functions["Fun"..InAICode.RoleCount] = function(action)		--获得游戏玩家的数量
		roleCount = action[2];
	end

	role_Functions["Fun"..InAICode.Ready] = function(action)            --玩家场景加载完毕
		currentReady = currentReady + 1;
	end

	role_Functions["Fun"..InAICode.ReadySchedule] = function(action)          --玩家进入一个战斗区域，当副本中所有的玩家都进入到该区域时，将触发区域内的怪物
		if action[2] == 0 then                      --退出战斗区域
			readyFightCount = readyFightCount - 1;
		elseif action[2] == 1 then                  --进入战斗区域
			readyFightCount = readyFightCount + 1;
		end
		if readyFightCount == roleCount then
			readNext = 1;
		end
		-- coroutine.yield(readNext.."~~"..readyFightCount);
	end

	role_Functions["Fun"..InAICode.Move] = function(action)					--玩家移动方法
		--op  id  x  y
		if roles["Role"..action[2]] ~= nil then
			if roles["Role"..action[2]].x ~= action[3] or roles["Role"..action[2]].y ~= action[4] then      --玩家进行移动
				roles["Role"..action[2]].x = action[3];
				roles["Role"..action[2]].y = action[4];
				roles["Role"..action[2]].move = 1;
				-- coroutine.yield("movebefor"..roles["Role"..action[2]].x..":"..roles["Role"..action[2]].y);
				-- coroutine.yield("moveafter"..action[3]..":"..action[4]);
			end
		end
	end

	role_Functions["Fun"..InAICode.CastSkill] = function(action)			--玩家施放技能回调方法
		-- op id posX posY dirX dirY
		local skillData = Skills["skill"..action[2]];				--获取技能数据
		-- Skills: type l&h/r
		if skillData[1] == 1 then		--长方形
									--x  y  dirx  diry  l  h
									--	x0	y0	x1	y1	x2	y2	x3	y3
		-- coroutine.yield(boxGetPoint({x = action[3], y = action[4]}, {x = action[5], y = action[6]}, skillData[2], skillData[3]));
		
		local p1, p2, p3, p4 = boxGetPoint({x = action[3], y = action[4]}, {x = action[5], y = action[6]}, skillData[2], skillData[3]);
		table.insert(skill_Box, {p1, p2, p3, p4});									

		elseif skillData[1] == 2 then   --圆形
									--x  y  r
			table.insert(skill_Round, {action[3], action[4], skillData[2]});
		elseif skillData[1] == 3 then   --全屏
									--hp
			table.insert(skill_Full, {action[3]});
		end
	end

	local function mon_Function(mon)		--怪物AI处理函数
		local self_mon = mon;
		local hasTarget = 0;				--是否有攻击目标
		local target_Role = nil;			--攻击目标
		local timer = 0;					--计时器
		local attacking = 0;
		local move_Timer = 0;
		local move_TimeL = 0;
		local lastX = self_mon.x;
		local lastY = self_mon.y;
		local run = 1;
		while run == 1 do
			-- if hasTarget == 1 then
			-- 	coroutine.yield("x"..target_Role.x.."::".."y"..y..target_Role.y);
			-- end

			if hasTarget == 0 or recheck_Target == 1 then                            --没有目标，搜索目标
				target_Role = getMinRole(self_mon, roles);
				table.insert(result, {OutAICode.Target, target_Role.id, self_mon.id});			--确定目标
				hasTarget = 1;
			end

			if hasTarget == 1 and target_Role.move == 1 and move_TimeL ~= 0 then
				local moveScale = move_Timer / move_TimeL;
				self_mon.x = (self_mon.x - lastX) * moveScale + lastX;
				self_mon.y = (self_mon.y - lastY) * moveScale + lastY;
				move_Timer = 0;
				move_TimeL = 0;
				-- target_Role.move = 0;
			end


			local fartorole = getlenp({x=self_mon.x, y=self_mon.y}, target_Role);
			-- if attacking == 0 then                                                    --怪物还没有进行攻击
				if move_Timer < move_TimeL or move_Timer == move_TimeL then              --正在进行移动
					move_Timer = move_Timer + scaleTime;
					coroutine.yield("move");
                elseif fartorole < self_mon.scope * self_mon.scope and hasTarget == 1 and attacking == 0 then			                                 --怪物有攻击目标且在攻击范围之内
					coroutine.yield(fartorole..":::"..self_mon.scope * self_mon.scope);
					attacking = 1 			                								--开始进行攻击
					-- coroutine.yield("start fight");
					table.insert(result, {OutAICode.EnterFight, self_mon.id});									--开始播放攻击动画
					target_Role.HP = target_Role.HP - self_mon.AD;
					-- coroutine.yield("HP:"..target_Role.id..":"..target_Role.HP);
					table.insert(result, {OutAICode.CurrentHP, 1, target_Role.id, target_Role.HP});--TODO怪物攻击角色伤害计算，回发玩家的HP
					-- coroutine.yield("timer:"..move_Timer.."  timel:"..move_TimeL);
				elseif fartorole > self_mon.scope * self_mon.scope	then       --目标在怪物的攻击范围之外
					-- coroutine.yield("far......................");
					-- coroutine.yield("too far..............."..getlenp({x=self_mon.x, y=self_mon.y}, target_Role)..":"..self_mon.scope * self_mon.scope);
                	local vectorX, vectorY, far = normalize(self_mon, target_Role);		--开始执行移动操作
					-- coroutine.yield("selfx"..self_mon.x.."  selfy"..self_mon.y);
					-- coroutine.yield("targetx"..target_Role.x.."  targety"..target_Role.y);
					if far > self_mon.scope and far < 10000 then
						far = far - self_mon.scope + 0.01;
						lastX = self_mon.x;
						lastY = self_mon.y;
						self_mon.x = self_mon.x + vectorX * far + math.random(0, self_mon.scope * 2);
						self_mon.y = self_mon.y + vectorY * far + math.random(0, self_mon.scope * 2);
						move_Timer = 0;
						move_TimeL = far / self_mon.speed;
						table.insert(result, {OutAICode.Position, self_mon.id, self_mon.x, self_mon.y});			--刷新位置
					end
					-- coroutine.yield("code:"..OutAICode.Position.."  id:"..self_mon.id.."  x:"..self_mon.x.."  y:"..self_mon.y);
					-- coroutine.yield("flash Position"..move_Timer..":"..move_TimeL);
				end
			-- end

			if attacking == 1 then                      --正在播放攻击动画
				timer = timer + scaleTime;
				-- coroutine.yield(timer.."::"..self_mon.CD);
				if timer > self_mon.CD then             --动画播放结束
					attacking = 0;
					timer = 0;
					-- move_Timer = 0;
					-- move_TimeL = 0;
				end
			end

			if target_Role.HP < 0 or target_Role.HP == 0 then                   --攻击目标死亡
				table.insert(result, {OutAICode.Die, 1, target_Role.id});
				if table.concat(target_Role) then                               --将已死亡的玩家从玩家列表中剔除
					for j,w in ipairs(roles) do
						if target_Role == w then
							table.remove(roles, j);
						end
					end
				end
				target_Role = nil;
				hasTarget = 0;

				if table.getn(roles) == 0 then                                      --获取当前玩家数量，数量为0时则游戏结束
					table.insert(result, {OutAICode.GameOver, 0});						--返回AI结束消息，脚本和启动器都将结束运行
					run = 0;
				end
			end

			for _,v in ipairs(skill_Box) do
				if boxSolu(self_mon, v[1], v[2], v[3], v[4]) == 1 then 
					self_mon.HP = self_mon.HP - 3;
					table.insert(result, {OutAICode.CurrentHP, 0, self_mon.id, self_mon.HP});
				end
				-- coroutine.yield("Box");
			end

			for _,v in ipairs(skill_Round) do
				if getlenp({x = v[1], y = v[2]}, self_mon) < v[3] * v[3] then
					self_mon.HP = self_mon.HP - 3;
					table.insert(result, {OutAICode.CurrentHP, 0, self_mon.id, self_mon.HP});
				end
				coroutine.yield(getlenp({x = v[1], y = v[2]}, self_mon).."::"..v[3] * v[3]);
				-- coroutine.yield("Round");
			end

			for _,v in ipairs(skill_Full) do
				for _,w in ipairs(roles) do
					w.HP = w.HP + 10;
					table.insert(result, {OutAICode.CurrentHP, 1, w.id, w.HP});
				end
				-- coroutine.yield("Full");
			end

			if self_mon.HP < 0 or self_mon.HP == 0 then
				run = 0;
				table.insert(result, {OutAICode.Die, 0, self_mon.id});
			end

			coroutine.yield();
		end
	end 

	while waitflag do
		if _G.action ~= nil then                           --收到从客户端发送过来的操作
			-- coroutine.yield("action".._G.action[1]);
			role_Functions["Fun".._G.action[1]](_G.action);
			_G.action = nil;
		end
		if currentReady == roleCount and currentReady ~= 0 then
			waitflag = nil;
		end
		coroutine.yield();
	end

	while true do
		-- coroutine.yield(table.getn(current_Mons).."::"..readNext);
		if table.getn(mon_Threads) == 0 then               --当前区域内的怪物被清理干净
			if shcedule > 2 then
				--副本已经打完，游戏结束
				table.insert(result, {OutAICode.GameOver, 1});
			elseif readNext == 1 then
				readNext = 0;
				-- coroutine.yield("kill over");
				current_Mons = Mons[shcedule];					--读取下一区域内的怪物
				shcedule = shcedule + 1;
				for i,v in ipairs(current_Mons) do
					table.insert(result, {OutAICode.Born, v.id, v.typeid, v.x, v.y, v.HP});		--出生
					local current_Mon = coroutine.create(mon_Function);
					coroutine.yield(coroutine.resume(current_Mon, v));
					mon_Static = nil;
					table.insert(mon_Threads, current_Mon);				--将该怪物添加到怪物线程集合
					-- coroutine.yield("join~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"..v.id);
				end		--生成怪物
			end
		end

		if _G.action ~= nil then                           --收到从客户端发送过来的操作
			-- coroutine.yield("action".._G.action[1]);
			role_Functions["Fun".._G.action[1]](_G.action);
			_G.action = nil;
		end
			
		local monRemoveList = {};
		for _,v in ipairs(mon_Threads) do               --遍历整个怪物列表，并轮流启动它们
			if coroutine.status(v) == "dead" then
				table.insert(monRemoveList, v);
			else
				coroutine.yield(coroutine.resume(v));
			end
		end
		for _,v in ipairs(monRemoveList) do
			for i,_ in ipairs(mon_Threads) do
				if mon_Threads[i] == v then
					table.remove(mon_Threads, i);
					-- coroutine.yield("remove......................");
				end
			end
			-- coroutine.yield("mon_Threads.length......................."..table.getn(mon_Threads));
			if table.getn(mon_Threads) == 0 then
				table.insert(result, {OutAICode.CurrentOver, 1});
			end
		end

		for _,v in pairs(roles) do
			v.move = 0;
		end
		skill_Box = {};
		skill_Round = {};
		skill_Round = {};
		coroutine.yield(result);
		result = {};
	end
end

function Destory()
	-- body
end



